package com.bbm.communitysystem.controller.post;


import cn.hutool.core.bean.BeanUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.bbm.communitysystem.core.domain.FileStatus;
import com.bbm.communitysystem.core.domain.R;
import com.bbm.communitysystem.core.oss.OSS;
import com.bbm.communitysystem.core.redis.PostRedis;
import com.bbm.communitysystem.domain.*;
import com.bbm.communitysystem.domain.bo.PostBo;
import com.bbm.communitysystem.domain.dto.post.PostDto;
import com.bbm.communitysystem.domain.vo.*;
import com.bbm.communitysystem.service.ILikePostService;
import com.bbm.communitysystem.service.IPostService;
import com.bbm.communitysystem.service.IUserInfoService;
import com.bbm.communitysystem.service.impl.CommentServiceImpl;
import com.bbm.communitysystem.service.impl.OssFileServiceImpl;
import com.bbm.communitysystem.tools.DemoDate;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.Parameters;
import io.swagger.v3.oas.annotations.tags.Tag;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import java.util.*;
import java.util.stream.Collectors;

/**
 * <p>
 *  帖子 前端控制器
 * </p>
 *
 * @author transitory
 * @since 2025-02-20
 */

@Tag(name = "帖子")
@Slf4j
@RestController
@RequestMapping("/post")
@RequiredArgsConstructor
public class PostController {

    private final IPostService postService;

    private final IUserInfoService userInfoService;

    private final OssFileServiceImpl ossFileService;

    private final ILikePostService likePostService;

    private final CommentServiceImpl commentService;

    private final PostRedis postRedis;

    private final OSS oss;

    /**
     * 新增帖子 APi
     * */
    @Operation(summary = "新增帖子")
    @PostMapping
    public R<String> addPost(@RequestBody PostDto postDto){
        Post post = BeanUtil.copyProperties(postDto, Post.class);
        post.setUserId(post.getUpdateBy());
        post.setStatus(2);
        post.setLikes(0);
        post.setComment(0);
        post.setForward(0);
        post.setInterest(0);
        post.setUpdateTime(System.currentTimeMillis() + "");
        boolean save = postService.save(post);

        return save ? R.ok("添加成功", post.getId() + "") : R.error("");
    }

    /**
     * 修改帖子 API
     * */
    @Operation(summary = "发布帖子")
    @PutMapping
    public R<String> modifyPost(@RequestBody PostDto postDto){
        PostBo postBo = BeanUtil.copyProperties(postDto, PostBo.class);

        postBo.setStatus(3);
        postBo.setUpdateTime(System.currentTimeMillis() + "");
        postBo.setType(postDto.getType());
        PostDto postDto1 = postService.putPostInfo(postBo);

        return postDto1 != null ? R.ok("修改成功") : R.error("修改失败");
    }

    @Operation(summary = "保存帖子")
    @PutMapping("/save")
    public R<String> savePost(@RequestBody PostDto postDto) {
        PostBo postBo = BeanUtil.copyProperties(postDto, PostBo.class);

        postBo.setStatus(2);
        postBo.setUpdateTime(System.currentTimeMillis() + "");
        postBo.setType(postDto.getType());
        PostDto postDto1 = postService.putPostInfo(postBo);

        return postDto1 != null ? R.ok("修改成功") : R.error("修改失败");
    }


    /**
     * 删除帖子 API
     * */
    @Operation(summary = "删除帖子")
    @DeleteMapping
    @Parameters({
            @Parameter(name = "id", description = "帖子ID"),
            @Parameter(name = "user", description = "用户ID")
    })
    public R<String> deletePost(@RequestParam("id") Integer postId, @RequestParam("user") Integer id){

        boolean remove = postService.lambdaUpdate()
                .eq(Post::getUserId,id)
                .eq(Post::getId,postId)
                .set(Post::getStatus,0)
                .update();


        return remove ? R.ok("删除成功"): R.error("删除失败");
    }


    @GetMapping("/del")
    public R<String> delAllPost() {

        postService.list().forEach(i -> {

            postService.lambdaUpdate()
                    .eq(Post::getUserId,i.getUserId())
                    .eq(Post::getId, i.getId())
                    .set(Post::getStatus,0)
                    .update();

        });


        return R.ok();
    }



    @Operation(summary = "删除编辑中的帖子", description = "删除编辑中的帖子")
    @DeleteMapping("/edit")
    @Parameters({
            @Parameter(name = "id", description = "帖子ID"),
            @Parameter(name = "user", description = "用户ID")
    })
    public R deleteEditPost(@RequestParam("id") Integer postId, @RequestParam("user") Integer id) {

        Post one = postService.lambdaQuery()
                .eq(Post::getUserId, id)
                .eq(Post::getStatus, 2)
                .eq(Post::getId, postId)
                .one();

        if (one == null) {
            return R.error("帖子不存在");
        }

        if (one.getOssId() != null) {
            String[] split = one.getOssId().split(",");

            for (String s : split) {
                OssFile one1 = ossFileService.getById(s);
                if (one1 == null) {
                    continue;
                }
                oss.deleteFile(one1.getId());
            }
        }

        boolean b = postService.removeById(postId);

        return b ? R.ok("删除成功") : R.error("删除失败");
    }

    /**
     * 获取已公布帖子列表
     * 这里 latitude(观看权限) 还没有定义
     *
     * @param page 页码
     * @param size 每页数量
     * */
    @Operation(summary = "获取已公布帖子列表", description = "用户点赞过的不会被显示")
    @GetMapping
    @Parameters({
            @Parameter(name = "page", description = "第几页"),
            @Parameter(name = "size", description = "多少")
    })
    public R<PageVo<PostVo>>  getPostList(@RequestParam("page") Integer page,
                                          @RequestParam("size") Integer size) {
        Page<Post> postPage = new Page<>(page,size);

        LambdaQueryWrapper<Post> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(Post::getStatus,1);
        queryWrapper.orderByDesc(Post::getUpdateTime);

        Page<Post> page1 = postService.page(postPage, queryWrapper);
        PageVo<PostVo> postVoPageVo = new PageVo<>(page1);
        page1.getRecords().forEach(post -> {
            postVoPageVo.getRecords().add(getPostVo(post));
        });



        return R.ok("获得所有已公布的信息列表成功",postVoPageVo);
    }


    /**
     * 获得用户未发布和审核和审核不通过的帖子
     * */
    @Operation(summary = "获得用户未发布和审核和审核不通过的帖子")
    @PostMapping("/userPost")
    public R<PageVo<EditPostVo>> getUserPost(@RequestBody PostDto postDto){

        Page<Post> postPage = new Page<>(postDto.getPage(), postDto.getSize());

        LambdaQueryWrapper<Post> lambdaQueryWrapper = new LambdaQueryWrapper<>();
        lambdaQueryWrapper.eq(Post::getUserId, postDto.getUpdateBy())
                .eq(Post::getStatus,2);

        Page<Post> page = postService.page(postPage, lambdaQueryWrapper);

        PageVo<EditPostVo> postVoPageVo = new PageVo<>(page);

        page.getRecords().forEach(item -> {
            List<OssFileVo> list = new ArrayList<>();
            EditPostVo editPostVo = new EditPostVo();
            editPostVo.setId(item.getId());
            editPostVo.setContent(item.getContent());
            editPostVo.setType(item.getType());
            String ossId1 = item.getOssId();

            if (ossId1 == null) {
                ossId1 = "";
            } else {
                String[] ossIds = ossId1.split(",");

                for (String ossId : ossIds) {
                    OssFile byId = ossFileService.getById(ossId);
                    if (byId == null) {
                        continue;
                    }

                    OssFileVo ossFileVo = new OssFileVo();
                    ossFileVo.setType(byId.getFileType());
                    ossFileVo.setClientUrl(byId.getClientUrl());
                    ossFileVo.setId(byId.getId());
                    list.add(ossFileVo);
                }
            }


            editPostVo.setFile(list);
            postVoPageVo.getRecords().add(editPostVo);
        });


        return R.ok("获得用户未发布的表信息成功", postVoPageVo);
    }





    @Operation(summary = "上传图片")
    @PostMapping("/img")
    @Parameters({
            @Parameter(name = "postId", description = "帖子ID"),
            @Parameter(name = "user", description = "用户ID"),
            @Parameter(name = "img", description = "图片")
    })
    public R<String> uploadPostImg(@RequestParam("postId") Integer postId,
                                   @RequestParam("user") Integer id, @RequestParam("img") MultipartFile file) {

        Post byId1 = postService.getById(postId);

        if (byId1 == null) {
            return R.error("帖子不存在");
        }

        String ossId1 = byId1.getOssId();

        if (ossId1 == null) {
            ossId1 = "";
        }

        String[] split = ossId1.split(",");

        int imgIndex = 0;

        for (String s : split) {
            OssFile byId = ossFileService.getById(s);
            if (byId == null) {
                continue;
            }
            if (byId.getFileType().equals("m4v") || byId.getFileType().equals("mp4") || byId.getFileType().equals("avi")) {
                return R.error("一个帖子只能上传一张图片");
            }

            if (byId.getFileType().equals("jpg") || byId.getFileType().equals("png") || byId.getFileType().equals("jpeg") || byId.getFileType().equals("gif")) {
                imgIndex++;
            }

            if (imgIndex >= 9) {
                return R.error("一个帖子只能上传9张图片");
            }

        }


        List<OssFile> postImg = oss.saveFile("postImg", id + "", file);

        if (postImg.isEmpty()) {
            return R.error("上传失败");
        }

        Post byId = postService.getById(postId);

        String ossId = byId.getOssId();

        StringBuilder builder = new StringBuilder();

        for (OssFile ossFile : postImg) {
            builder.append(ossFile.getId()).append(",");
        }

        builder.delete(builder.length() - 1, builder.length());

        if (ossId == null || ossId.isEmpty()) {
            ossId = builder.toString();
        } else {
            ossId = ossId + "," + builder;
        }

        byId.setOssId(ossId);

        boolean b = postService.updateById(byId);

        return b ? R.ok("上传成功", postImg.get(0).getClientUrl()) : R.error("上传失败");
    }

    @Operation(summary = "删除帖子的文件", description = "删除帖子的一个文件")
    @DeleteMapping("/delImg")
    @Parameters({
            @Parameter(name = "postId", description = "帖子ID"),
            @Parameter(name = "img", description = "图片ID"),
            @Parameter(name = "user", description = "用户ID")
    })
    public R<String> delPostImg(@RequestParam("postId") Integer postId, @RequestParam("img") Integer id, @RequestParam("user") Integer userId) {

        Post post = postService.getById(postId);

        String[] split = post.getOssId().split(",");
        StringBuilder builder = new StringBuilder();
        for (String s : split) {
            if (s.equals(id + "")) {
                oss.deleteFile(id);
                log.info("删除文件成功，帖子ID：{}，文件id：{}，用户id:{}", postId, id, userId);
            } else {
                builder.append(s).append(",");
            }
        }

        if (builder.length() > 1) {
            builder.delete(builder.length() - 1, builder.length());
        }

        post.setOssId(builder.toString());
        boolean b = postService.updateById(post);

        return b ? R.ok("删除成功") : R.error("删除失败");
    }


    //接受视频
    @PostMapping("/video")
    public R uploadVideo(@RequestParam("video") MultipartFile file, @RequestParam("postId") Integer postId,
                         @RequestParam("user") Integer id, @RequestParam("originFileName") String originFileName,
                         @RequestParam("chunkHash") String chunkHash, @RequestParam("Hash") String hash,
                         @RequestParam("index") Integer index) {

        if (chunkHash.equals("end")) {

            OssFile ossFile = oss.saveBigFile("postVideo", id + "", hash, originFileName);

            if (ossFile == null) {
                return R.error("文件合并失败");
            }


            PostBo postBo = new PostBo();

            postBo.setId(postId);
            postBo.setUpdateBy(id);
            postBo.setUpdateTime(System.currentTimeMillis() + "");
            postBo.setOssId(ossFile.getId() + "");
            postBo.setStatus(2);

            PostDto postDto = postService.putPostInfo(postBo);

            if (postDto == null) {
                return R.error("数据库信息更新失败");
            }

            return R.ok("文件合并", ossFile.getClientUrl());
        } else {

             Boolean b = oss.saveCheckFile(file, hash, id + "", index + "");

             return b ? R.ok("上传成功") : R.error("上传失败");
        }

    }




    @Operation(summary = "获取视频上传状态", description = "一个帖子只能上传一个视频")
    @GetMapping("/videoStatus/{hash}")
    @Parameters({
            @Parameter(name = "postId", description = "帖子ID"),
            @Parameter(name = "user", description = "用户ID"),
            @Parameter(name = "hash", description = "视频hash"),
    })
    public R<FileStatus> getUploadVideoStatus(@PathVariable("hash") String videoHash,
                                              @RequestParam("user") Integer id, @RequestParam("postId") Integer postId) {
        if (videoHash == null || videoHash.isEmpty()) {
            return R.error("视频hash不能为空");
        }

        FileStatus uploadStatus = oss.getUploadStatus(videoHash);

        if (uploadStatus.getCurrentChunk() == null) {
            Post byId = postService.getById(postId);

            String ossId = byId.getOssId();

            if (ossId == null || ossId.isEmpty()) {
                return R.ok("获取成功", uploadStatus);
            }

            String[] split = ossId.split(",");

            for (String s : split) {
                OssFile byId1 = ossFileService.getById(s);
                if (byId1 != null) {
                    return R.error("一个帖子只能有一个视频！且不能有图片");
                }
            }

        }

        return R.ok("获取成功", uploadStatus);
    }

    @Operation(summary = "停止上传视频", description = "停止上传视频并且删除缓存")
    @DeleteMapping("/stopUploadVideo")
    @Parameters({
            @Parameter(name = "user", description = "用户ID"),
            @Parameter(name = "hash", description = "视频hash"),
    })
    public R<FileStatus> stopUploadVideo(@RequestParam("hash") String videoHash, @RequestParam("user") Integer id) {

        FileStatus fileStatus = oss.stopUploadAndDel(videoHash, id + "");

        return R.ok("停止成功", fileStatus);
    }

    @Operation(summary = "获得已公布帖子详情")
    @GetMapping("/{id}")
    @Parameters({
            @Parameter(name = "id", description = "帖子ID")
    })
    public R<PostDeVo> getPostById (@PathVariable("id") Integer id) {
        Post one;

        //redis查询
        one = postRedis.getPost(id + "_" + "1");


        if (one == null) {
            one = postService.lambdaQuery()
                    .eq(Post::getId, id)
                    .eq(Post::getStatus, 1)
                    .one();

            postRedis.setPost(id + "_" + "1", one);
        }



        if (one == null) {
            return R.error("帖子不存在");
        }

        PostDeVo postVo = new PostDeVo();

        UserInfo Author = userInfoService.getById(one.getUserId());
        String[] split;
        String ossId = one.getOssId();


        if (ossId == null) {
            split = new String[]{};
        } else {
            split = ossId.split(",");
        }


        List<OssFileVo> ossFileVos = new ArrayList<>();

        for (String s : split) {
            OssFile byId = ossFileService.getById(s);
            OssFileVo ossFileVo = new OssFileVo();
            ossFileVo.setType(byId.getFileType());
            ossFileVo.setClientUrl(byId.getClientUrl());
            ossFileVo.setId(byId.getId());
            ossFileVos.add(ossFileVo);
        }


        //点赞的用户
        List<LikePost> list = likePostService.lambdaQuery()
                .eq(LikePost::getSourceId, id)
                .eq(LikePost::getStatus, 1)
                .list();

        List<Integer> userId = new ArrayList<>();

        list.forEach(item -> {
            userId.add(item.getFounder());
        });

        //评论
        List<Comment> list1 = commentService.lambdaQuery()
                .eq(Comment::getPostId, id)
                .eq(Comment::getStatus, 1)
                .list();

        List<CommentVo> commentVos = new ArrayList<>();

        list1.forEach(item -> {
            UserInfo userInfo = userInfoService.getById(item.getUserId());

            CommentVo commentVo = new CommentVo();
            commentVo.setId(item.getId());
            commentVo.setContent(item.getContent());
            commentVo.setAvatar(userInfo.getUserImg());
            commentVo.setNickName(userInfo.getUserNick());
            String createTime1 = item.getCreateTime();


            commentVo.setTime(DemoDate.getPostDate(createTime1));

            commentVo.setCommentLike(item.getCommentLike());
            commentVo.setStepId(item.getStepId());
            commentVo.setComment(item.getComment());


            List<LikePost> likePosts = likePostService.lambdaQuery()
                    .eq(LikePost::getSourceId, item.getId())
                    .eq(LikePost::getStatus, 1)
                    .eq(LikePost::getType, 1)
                    .list();

            commentVo.setUserId(new ArrayList<>());

            likePosts.forEach(item1 -> {
                commentVo.getUserId().add(item1.getFounder());
            });


            if (item.getOssId() != null) {
                OssFile byId = ossFileService.getById(item.getOssId());

                if (byId != null) {
                    commentVo.setFileClient(byId.getClientUrl());
                }
            } else {
                commentVo.setFileClient(null);
            }

            commentVos.add(commentVo);
        });


        postVo.setId(one.getId());
        postVo.setContent(one.getContent());
        postVo.setAvatar(Author.getUserImg());
        postVo.setNickName(Author.getUserNick());
        postVo.setFile(ossFileVos);
        postVo.setType(one.getType());
        postVo.setLikeNum(one.getLikes());
        postVo.setCommentNum(commentVos.size());
        postVo.setLikesId(userId);

        postVo.setTime(DemoDate.getPostDate(one.getUpdateTime()));

        List<CommentVo> tree = new ArrayList<>();

        //获取一级评论
        for (CommentVo commentVo : commentVos) {
            if (commentVo.getStepId() == 0) {
                tree.add(commentVo);
            }
        }

        for (CommentVo commentVo : tree) {
            List<CommentVo> commentVo1 = commentVoTree(commentVos, commentVo);
            commentVo.setChildComment(commentVo1);
        }


        postVo.setComments(tree);



        return R.ok("获取成功", postVo);
    }


    @Operation(summary = "获得用户所有帖子")
    @GetMapping("/userPost")
    @Parameters({
            @Parameter(name = "userId", description = "用户ID"),
            @Parameter(name = "page", description = "页码"),
            @Parameter(name = "size", description = "每页数量")
    })
    public R<PageVo<PostVo>> getUserAllPost(
            @RequestParam("userId") Long userId,
            @RequestParam(value = "page", defaultValue = "1") Integer page,
            @RequestParam(value = "size", defaultValue = "10") Integer size) {

        Page<Post> postPage = new Page<>(page, size);
        LambdaQueryWrapper<Post> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(Post::getUserId, userId)
                .ne(Post::getStatus, 0)
                .orderByDesc(Post::getUpdateTime);

        Page<Post> pageResult = postService.page(postPage, queryWrapper);
        PageVo<PostVo> postVoPageVo = new PageVo<>(pageResult);

        pageResult.getRecords().forEach(post -> {
            PostVo postVo = new PostVo();
            // 基础信息复制
            BeanUtil.copyProperties(post, postVo);

            // 用户信息处理
            UserInfo user = userInfoService.getById(userId);
            postVo.setAvatar(user.getUserImg());
            postVo.setNickName(user.getUserNick());



            postVo.setTime(post.getPublicTime());


            // 文件处理
            List<OssFileVo> fileVos = new ArrayList<>();
            if (post.getOssId() != null) {
                Arrays.stream(post.getOssId().split(","))
                        .map(ossFileService::getById)
                        .filter(Objects::nonNull)
                        .forEach(ossFile -> {
                            OssFileVo vo = new OssFileVo();
                            BeanUtil.copyProperties(ossFile, vo);
                            vo.setType(ossFile.getFileType());
                            fileVos.add(vo);
                        });
            }
            postVo.setFile(fileVos);

            // 点赞信息处理
            List<Integer> likesId = likePostService.lambdaQuery()
                    .eq(LikePost::getSourceId, post.getId())
                    .eq(LikePost::getStatus, 1)
                    .list()
                    .stream()
                    .map(LikePost::getFounder)
                    .collect(Collectors.toList());
            postVo.setLikesId(likesId);

            postVoPageVo.getRecords().add(postVo);
        });

        return R.ok("获取成功", postVoPageVo);
    }



    private List<CommentVo> commentVoTree(List<CommentVo> list,CommentVo curComment) {
        List<CommentVo> commentVos = new ArrayList<>();
        for (CommentVo commentVo : list) {
            if (commentVo.getStepId() == null) {
                continue;
            }

            if (commentVo.getStepId().equals(curComment.getId())) {
                commentVos.add(commentVo);
                List<CommentVo> commentVos1 = commentVoTree(list, commentVo);
                commentVos.addAll(commentVos1);
            }

        }
        return commentVos;
    }



    private PostVo getPostVo(Post post) {

        List<OssFileVo> fileVos = new ArrayList<>();
        String ossId = post.getOssId();
        String[] split;
        if (ossId == null) {
            split = new String[]{};
        } else {
            split = ossId.split(",");
        }


        for (String s : split) {
            OssFile ossFile = ossFileService.getById(s);
            if (ossFile == null) {
                continue;
            }
            OssFileVo ossFileVo = new OssFileVo();
            ossFileVo.setType(ossFile.getFileType());
            ossFileVo.setClientUrl(ossFile.getClientUrl());
            fileVos.add(ossFileVo);
        }

        PostVo postVo = new PostVo();
        postVo.setId(post.getId());
        postVo.setContent(post.getContent());
        postVo.setAvatar(userInfoService.getById(post.getUserId()).getUserImg());
        postVo.setType(post.getType());
        postVo.setNickName(userInfoService.getById(post.getUserId()).getUserNick());
        postVo.setTime(DemoDate.getPostDate(post.getUpdateTime()));
        postVo.setLikeNum(post.getLikes() == null ? 0 : post.getLikes());
        postVo.setCommentNum(post.getComment() == null? 0 : post.getComment());

        List<LikePost> list = likePostService.lambdaQuery()
                .eq(LikePost::getSourceId, post.getId())
                .eq(LikePost::getStatus, 1)
                .list();

        postVo.setLikesId(new ArrayList<>());

        list.forEach(item -> {
            postVo.getLikesId().add(item.getFounder());
        });

        postVo.setFile(fileVos);

        return postVo;
    }



}
